const redis = require('redis');
const hasher = require("pbkdf2-password")({
    saltLength: 12
});
const db = redis.createClient();

class User {
    constructor(obj) {
        for (let key in obj) {
            this[key] = obj[key];
        }
    }

    toJSON() {
        return {
            id: this.id,
            name: this.name
        }
    }

    static getByName(name, cb) {
        // 根据名称查找用户ID
        User.getId(name, (err, id) => {
            if (err) return cb(err);
            // 用ID抓取用户
            User.get(id, cb);
        })
    }

    static getId(name, cb) {
        // 取得由名称索引得ID
        db.get(`user:ids:${name}`, cb);
    }

    static get(id, cb) {
        // 获取普通对象哈希
        db.hgetall(`user:${id}`, (err, user) => {
            if (err) return cb(err);
            // 将普通对象转成新得User对象
            cb(null, new User(user));
        })
    }

    static authenticate(name, pass, cb) {
        // 通过用户名查找用户
        User.getByName(name, (err, user) => {
            if (err) return cb(err);
            // 用户不存在
            if (!user.id) return cb();
            // 对给出得密码做hash处理
            hasher({ password: pass, salt: user.salt }, (err, pass, salt, hash) => {
                if (err) return cb(err);
                // 匹配发现项
                if (hash === user.pass) return cb(null, user);
                // 密码无效
                cb();
            })
        })
    }
    save(cb) {
        if (this.id) {
            this.update(cb);
        } else {
            db.incr('user:ids', (err, id) => {
                if (err) return cb(err);
                this.id = id;
                this.hashPassword(err => {
                    if (err) return cb(err);
                    this.update(cb);
                })
            })
        }
    }

    update(cb) {
        const id = this.id;
        db.set(`user:ids:${this.name}`, id, (err) => {
            if (err) return cb(err);
            db.hmset(`user:${id}`, this, (err) => {
                // if (err) return cb(err);
                cb(err);
            })
        })
    }

    hashPassword(cb) {
        hasher({ password: this.pass }, (err, pass, salt, hash) => {
            if (err) return cb(err);
            this.pass = hash;
            this.salt = salt;
            cb();
        })
    }
}

module.exports = User;

// const User1 = require('./user');
// const user = new User1({ name: 'admin', pass: '123' });
// user.save(err => {
//     if (err) console.error(err);
//     console.log('user id %d', user.id);

// })